/**
 * Subject
 */
 export default class Subject {
    constructor() {
        /**
         * @type {SubjectListener[]}
         */
        this._obs = [];
    }
    on(eventName, callback, node) {
        this._obs.push(new SubjectListener(eventName, callback, node));
    }
    /**
     * @param {Node} node 
     * @param {string|undefined} eventName 
     * @param {Function|undefined} callback 
     * @returns {SubjectListener|null}
     */
    off(node, eventName, callback) {
        for (var i = 0; i < this._obs.length;) {
            let ls = this._obs[i];
            if (ls.node !== node) {
                i++;
                continue;
            }
            if (eventName && ls.eventName !== eventName) {
                i++;
                continue;
            }
            if (callback && ls.callback !== callback) {
                i++;
                continue;
            }
            return this._obs.splice(i, 1)[0];
        }
        return null;
    }
    emit(eventName, msg) {
        for (var i = 0; i < this._obs.length; i++) {
            if (this._obs[i].eventName === eventName) {
                this._obs[i].callback.call(this._obs[i].node, msg, eventName);
            }
        }
    }
    remit( msg, eventName ) {
        this.emit(eventName, msg);
    }
}

class SubjectListener {
    constructor(eventName, callback, node) {
        Object.assign(this, {
            eventName,
            callback,
            node
        });
    }
}